﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using SqlServer = DataCoreTechnologies.SqlServer;

namespace DataCoreTechnologies.Scribe.Business.Html
{
    internal class DatabaseDocument : Document
    {
        #region internal
        //Constructor
        internal DatabaseDocument(SqlServer.Database database)
        {
            DocumentType = DocumentType.Database;
            URL = "index." + database.Name + ".html";
            RootServer = database.Server;
            RootDatabase = database;
            _database = database;
        }
        //Properties
        internal override string DisplayName { get { return _database.Name; } }

        internal ViewsDocument ViewsDocument { get { return _viewsDocument; } }
        internal TablesDocument TablesDocument { get { return _tablesDocument; } }
        internal StoredProceduresDocument StoredProceduresDocument { get { return _storedProceduresDocument; } }
        internal FunctionsDocument FunctionsDocument { get { return _functionsDocument; } }
        internal DataTypesDocument DataTypesDocument { get { return _dataTypesDocument; } }
        internal SchemasDocument SchemasDocument { get { return _schemasDocument; } }
        internal ColumnsDocument ColumnsDocument { get { return _columnsDocument; } }
        internal IndexesDocument IndexesDocument { get { return _indexesDocument; } }
        internal DefaultValuesDocument DefaultValuesDocument { get { return _defaultValuesDocument; } }
        internal ParametersDocument ParametersDocument { get; private set; }
        internal TriggersDocument TriggersDocument { get; private set; }

        internal IEnumerable<ViewDocument> ViewDocuments
        {
            get
            {
                for (int index = 0; index < _viewDocuments.Count; index++)
                {
                    yield return _viewDocuments[index];
                }
            }
        }
        internal IEnumerable<TableDocument> TableDocuments
        {
            get
            {
                for (int index = 0; index < _tableDocuments.Count; index++)
                {
                    yield return _tableDocuments[index];
                }
            }
        }
        internal IEnumerable<StoredProcedureDocument> StoredProcedureDocuments
        {
            get
            {
                for (int index = 0; index < _storedProcedureDocuments.Count; index++)
                {
                    yield return _storedProcedureDocuments[index];
                }
            }
        }
        internal IEnumerable<FunctionDocument> FunctionDocuments
        {
            get
            {
                for (int index = 0; index < _functionDocuments.Count; index++)
                {
                    yield return _functionDocuments[index];
                }
            }
        }
        internal IEnumerable<IndexDocument> IndexDocuments
        {
            get
            {
                for (int index = 0; index < _indexDocuments.Count; index++)
                {
                    yield return _indexDocuments[index];
                }
            }
        }
        internal IEnumerable<TriggerDocument> TriggerDocuments
        {
            get
            {
                for (int index = 0; index < _triggerDocuments.Count; index++)
                {
                    yield return _triggerDocuments[index];
                }
            }
        }
        //Methods
        internal override string GetHtml()
        {
            if (_html == "")
            {
                Boolean evenRow = true;

                AddCssLine(@"      	.propertyColumn {width: 300px; word-wrap: break-word;}");

                #region Lambda
                Func<string, string, string> tableRow = (string property, string value) => 
                {
                    string returnValue = @"<tr class=""""><td class=""property"">" + property + @"</td><td class=""value"">";
                    if (evenRow == true)
                        returnValue = returnValue.Replace(@"class=""""", @"class=""evenRow""");
                    else 
                        returnValue = returnValue.Replace(@"class=""""", @"class=""oddRow""");

                    if (value == null | value == "")
                        returnValue += @"&nbsp;";
                    else
                        returnValue += value;
                    returnValue += @"</td></tr>";

                    evenRow = !evenRow;
                    return returnValue;
                };
                #endregion

                evenRow = true;
                AddBodyLine(@"<div id=""mainBody"">");
                
                string heirarchy = @"<h2 id=""topNav"">Location: <a href=""http://index.html"">" + RootServer.Name + 
                    @"</a> . " + ScrubHtml(_database.Name) + @"</h2>";
                AddBodyLine(heirarchy);
                AddBodyLine(@"<h2 id=""title"">" + ScrubHtml(_database.Name) + @" (SQL Server Relational Database)</h2>");

                AddBodyLine(@"<h2>");
                AddBodyLine(@"<img id=""img_databaseProperties"" src=""" + RootFolderPath + @"minus.jpg""> ");
                AddBodyLine(@"<a href=""javascript:;"" onmousedown=""toggleDiv('databaseProperties');"">Properties</a>");
                AddBodyLine(@"</h2>");
                AddBodyLine(@"<div id=""databaseProperties"">");
                AddBodyLine(@"<table>");
                AddBodyLine(@"<colgroup><col class=""propertyColumn"" /><col class=""valueColumn"" /></colgroup>");
                AddBodyLine(@"<tr><th>Property</th><th>Value</th></tr>");
                AddBodyLine(tableRow("Name", ScrubHtml(_database.Name)));
                //AddBodyLine(tableRow("Default Schema Id", ""));
                //AddBodyLine(tableRow("Owner", ""));
                AddBodyLine(tableRow("Database Collation", ScrubHtml(_database.CollationName)));
                AddBodyLine(tableRow("Data Space Usage (KB)", ScrubHtml(AddCommasToNumericString(_database.DataSpaceUsed.ToString()))));
                AddBodyLine(tableRow("Index Space Usage (KB)", ScrubHtml(AddCommasToNumericString(_database.IndexSpaceUsed.ToString()))));
                AddBodyLine(tableRow("Space Available (KB)", ScrubHtml(AddCommasToNumericString(_database.DataSpaceAvailable.ToString()))));
                AddBodyLine(tableRow("Database Size (KB)", ScrubHtml(AddCommasToNumericString(_database.DatabaseSize.ToString()))));
                AddBodyLine(tableRow("Creation Date", ScrubHtml(_database.CreateDate.ToString())));
                //AddBodyLine(tableRow("Database Version", ""));
                AddBodyLine(tableRow("Compatibility Level", ScrubHtml(_database.CompatibilityLevel.ToString())));
                AddBodyLine(tableRow("Description", ScrubHtml(_database.Description)));
                AddBodyLine(@"</table>");
                AddBodyLine(@"</div>");

                evenRow = true;
                AddBodyLine(@"<h2>");
                AddBodyLine(@"<img id=""img_databaseOptions"" src=""" + RootFolderPath + @"minus.jpg""> ");
                AddBodyLine(@"<a href=""javascript:;"" onmousedown=""toggleDiv('databaseOptions');"">Options</a>");
                AddBodyLine(@"</h2>");
                AddBodyLine(@"<div id=""databaseOptions"">");
                AddBodyLine(@"<table>");
                AddBodyLine(@"<colgroup><col class=""propertyColumn"" /><col class=""valueColumn"" /></colgroup>");
                AddBodyLine(@"<tr><th>Property</th><th>Value</th><tr>");
                AddBodyLine(tableRow("Ansi Nulls Default", ScrubHtml(_database.IsAnsiNullDefaultOn.ToString())));
                AddBodyLine(tableRow("Ansi Null Enabled", ScrubHtml(_database.IsAnsiNullsOn.ToString())));
                AddBodyLine(tableRow("Ansi Padding Enabled", ScrubHtml(_database.IsAnsiPaddingOn.ToString())));
                AddBodyLine(tableRow("Ansi Warnings Enabled", ScrubHtml(_database.IsAnsiWarningsOn.ToString())));
                AddBodyLine(tableRow("Arithmetic Abort Enabled", ScrubHtml(_database.IsArithAbortOn.ToString())));                
                AddBodyLine(tableRow("Auto Close", ScrubHtml(_database.IsAutoCloseOn.ToString())));
                AddBodyLine(tableRow("Auto Create Statistics", ScrubHtml(_database.IsAutoCreateStatsOn.ToString())));
                AddBodyLine(tableRow("Auto Shrink", ScrubHtml(_database.IsAutoShrinkOn.ToString())));
                AddBodyLine(tableRow("Auto Update Statistics", ScrubHtml(_database.IsAutoUpdateStatsOn.ToString())));
                AddBodyLine(tableRow("Broker Enabled", ScrubHtml(_database.IsBrokerEnabled.ToString())));
                AddBodyLine(tableRow("Close Cursors On Commit Enabled", ScrubHtml(_database.IsCursorCloseOnCommitOn.ToString())));
                AddBodyLine(tableRow("Database Ownership Chaining", ScrubHtml(_database.IsDBChainingOn.ToString())));
                AddBodyLine(tableRow("Is Parameteriziation Forced", ScrubHtml(_database.IsParameterizationForced.ToString())));
                AddBodyLine(tableRow("Local Cursors Default", ScrubHtml(_database.IsLocalCursorDefault.ToString())));
                AddBodyLine(tableRow("Numeric Round Abort Enabled", ScrubHtml(_database.IsNumericRoundAbortOn.ToString())));
                AddBodyLine(tableRow("Page Verify Type", ScrubHtml(_database.PageVerifyOptionDescription)));
                AddBodyLine(tableRow("Quoted Identifiers Enabled", ScrubHtml(_database.IsQuotedIdentifierOn.ToString())));
                AddBodyLine(tableRow("Read Only", ScrubHtml(_database.IsReadOnly.ToString())));
                AddBodyLine(tableRow("Recovery Model", ScrubHtml(_database.RecoveryModelDescription)));
                //AddBodyLine(tableRow("Recursive Cursors Enabled", ""));
                AddBodyLine(tableRow("Snapshot Isolation State", ScrubHtml(_database.SnapshotIsolationStateDescription)));
                AddBodyLine(tableRow("Trustworthy", ScrubHtml(_database.IsTrustWorthyOn.ToString())));
                AddBodyLine(tableRow("Database User Access", ScrubHtml(_database.UserAccessDescription)));
                AddBodyLine(@"</table>");
                AddBodyLine(@"</div>");

                evenRow = true;
                AddBodyLine(@"<h2>");
                AddBodyLine(@"<img id=""img_extendedProperties"" src=""" + RootFolderPath + @"minus.jpg""> ");
                AddBodyLine(@"<a href=""javascript:;"" onmousedown=""toggleDiv('extendedProperties');"">Extended Properties</a>");
                AddBodyLine(@"</h2>");
                AddBodyLine(@"<div id=""extendedProperties"">");
                AddBodyLine(@"<table>");
                AddBodyLine(@"<colgroup><col class=""propertyColumn"" /><col class=""valueColumn"" /></colgroup>");
                AddBodyLine(@"<tr><th>Name</th><th>Value</th></tr>");
                foreach (SqlServer.ExtendedProperty extendedProperty in _database.ExtendedProperties)
                {
                    AddBodyLine(tableRow(ScrubHtml(extendedProperty.Name), ScrubHtml(extendedProperty.Value)));
                }
                AddBodyLine(@"</table>");
                AddBodyLine(@"</div>");

                AddBodyLine(@"</div>");

                _html = CreateHtmlDocument();
            } 
            return _html;
        }
        internal void ClearHtmlPages()
        {
           _viewsDocument = new ViewsDocument(_database);
           _tablesDocument = new TablesDocument(_database);
           _storedProceduresDocument = new StoredProceduresDocument(_database);
           _functionsDocument = new FunctionsDocument(_database);
           _dataTypesDocument = new DataTypesDocument(_database);
           _schemasDocument = new SchemasDocument(_database);
           _columnsDocument = new ColumnsDocument(_database);
           _indexesDocument = new IndexesDocument(_database);
           _defaultValuesDocument = new DefaultValuesDocument(_database);
           ParametersDocument = new ParametersDocument(_database);
           TriggersDocument = new TriggersDocument(_database);

           _viewDocuments.Clear();
           _tableDocuments.Clear();
           _storedProcedureDocuments.Clear();
           _functionDocuments.Clear();
           _indexDocuments.Clear();
           _triggerDocuments.Clear();
        }
        internal void CreateHtmlPages()
        {
            //Views
            var views = (from schema in _database.Schemas
                          from view in schema.Views
                          orderby view.Name
                          select view);
            foreach (SqlServer.View view in views)
            {
                ViewDocument viewDocument = new ViewDocument(view);
                _viewDocuments.Add(viewDocument);
            }

            //Tables
            var tables = (from schema in _database.Schemas
                          from table in schema.Tables
                          where table.Type == SqlServer.DatabaseObjectType.UserTable
                          orderby table.Name
                          select table);
            foreach (SqlServer.Table table in tables)
            {
                TableDocument tableDocument = new TableDocument(table);
                _tableDocuments.Add(tableDocument);
            }

            //Stored Procedures
            var storedProcedures = (from schema in _database.Schemas
                                   from storedProcedure in schema.StoredProcedures
                                   orderby storedProcedure.Name
                                   select storedProcedure);
            foreach (SqlServer.StoredProcedure storedProcedure in storedProcedures)
            {
                StoredProcedureDocument storedProcedureDocument = new StoredProcedureDocument(storedProcedure);
                _storedProcedureDocuments.Add(storedProcedureDocument);
            }

            //Functions
            var functions = (from schema in _database.Schemas
                             from function in schema.Functions
                             orderby function.Name
                             select function);
            foreach (SqlServer.Function function in functions)
            {
                FunctionDocument functionDocument = new FunctionDocument(function);
                _functionDocuments.Add(functionDocument);
            }

            //Indexes
            var tableIndexes = (from schema in _database.Schemas
                                from table in schema.Tables
                                from index in table.Indexes
                                select index);
            var viewIndexes = (from schema in _database.Schemas
                               from view in schema.Views
                               from index in view.Indexes
                               select index);
            var indexes = (from index in tableIndexes.Union(viewIndexes)
                           orderby index.Name
                           select index);

            foreach (SqlServer.Index index in indexes)
            {
                IndexDocument indexDocument = new IndexDocument(index);
                _indexDocuments.Add(indexDocument);
            }

            //Triggers
            var tableTriggers = (from schema in _database.Schemas
                                 from table in schema.Tables
                                 from trigger in table.Triggers
                                 select trigger);
            var databaseTriggers = (from trigger in _database.Triggers
                                    select trigger);
            var viewTriggers = (from schema in _database.Schemas
                                from view in schema.Views
                                from trigger in view.Triggers
                                select trigger);
            var triggers = (from trigger in tableTriggers.Union(databaseTriggers).Union(viewTriggers)
                            orderby trigger.Name
                            select trigger);
            foreach (SqlServer.Trigger trigger in triggers)
            {
                TriggerDocument triggerDocument = new TriggerDocument(trigger);
                _triggerDocuments.Add(triggerDocument);
            }
        }
        #endregion
        #region Private
        //Properties
        SqlServer.Database _database = null;

        private TablesDocument _tablesDocument;
        private ViewsDocument _viewsDocument;
        private StoredProceduresDocument _storedProceduresDocument;
        private FunctionsDocument _functionsDocument;
        private DataTypesDocument _dataTypesDocument;
        private SchemasDocument _schemasDocument;
        private ColumnsDocument _columnsDocument;
        private IndexesDocument _indexesDocument;
        private DefaultValuesDocument _defaultValuesDocument;

        private List<TableDocument> _tableDocuments = new List<TableDocument>();
        private List<ViewDocument> _viewDocuments = new List<ViewDocument>();
        private List<StoredProcedureDocument> _storedProcedureDocuments = new List<StoredProcedureDocument>();
        private List<FunctionDocument> _functionDocuments = new List<FunctionDocument>();
        private List<IndexDocument> _indexDocuments = new List<IndexDocument>();
        private List<TriggerDocument> _triggerDocuments = new List<TriggerDocument>();

        //Methods

        #endregion
    }
}
